<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\template\container\xhtml\instructions;

interface IForm
{
}

class ContainerForm extends Concrete implements IForm, IConcrete
{
  const ATTRIBUTE_FORM  = 'form';
  const ATTRIBUTE_FIELD = 'field';
  const ATTRIBUTE_JS    = 'js';

  public function start()
  {
    $oTrigger = new \crcl\base\template\Trigger();

    if ($this->hasAttribute(self::ATTRIBUTE_FIELD))
    {
      $oTrigger->setScope(
        \crcl\base\template\container\xhtml\Instruction::SCOPE_NEXT_ATTRIBUTE_SCAN);
    }
    else
    {
      $oTrigger->setScope(
        \crcl\base\template\container\xhtml\Instruction::SCOPE_CURRENT_NEXT_ATTRIBUTE);
    }
    $oTrigger->setInstruction($this);

    return $oTrigger;
  }

  public function executeCurrent()
  {
    $sForm = $this->getAttribute(self::ATTRIBUTE_FORM);
    $sForm = $this->fixVar($sForm);

    $sOutput = '';

    if ($this->hasAttribute('validation'))
    {
      $sField = $this->getAttribute('validation');

      $sOutput = '{$oValues->get(\'' . $sForm . '\')' .
        '->getValidationMessage(\'' . $sField . '\')}';
    }
    else
    {
      if ($this->hasAttribute(self::ATTRIBUTE_JS))
      {
        $sOutput =
          <<<BASE
          <script type="text/javascript">
<![CDATA[
  $(document).ready(function () {
    $('#%form%').parsley({
      successClass: 'has-success',
      errorClass: 'has-error',
      animate: 'false',
      validationMinlength: '0',
      validateIfUnchanged: true,
      trigger: 'keyup',
      errors: {
        classHandler: function(el) {
          return $(el).closest('.form-group');
        },
        errorsWrapper: '<p class=\"help-block\"></p>',
        errorElem: '<span></span>'
      }
    });
  });
]]>
</script>
BASE;
      }

      $sOutput = str_replace('%form%', $this->codeId($sForm), $sOutput);
    }
    $this->sContent = $sOutput;
  }

  public function executeNext($sTag, $aAttributes)
  {
    $this->aContentAttributes = $aAttributes;

    $sForm = $this->getAttribute(self::ATTRIBUTE_FORM);
    $sForm = $this->fixVar($sForm);

    if ($sTag == 'form')
    {
      $sEncoding = 'UTF-8';
      $sMethod = 'post';
      $sEncType = 'application/x-www-form-urlencoded';
      $sId = $this->codeId($sForm);

      $this->aContentAttributes['accept-charset'] = $sEncoding;
      $this->aContentAttributes['method'] = $sMethod;
      $this->aContentAttributes['enctype'] = $sEncType;
      $this->aContentAttributes['id'] = $sId;
      $this->aContentAttributes['novalidate'] = 'novalidate';
      $this->aContentAttributes['data-parsley-namespace'] = 'data-parsley-';
    }
  }

  public function executeScan($sTag, $aAttributes)
  {
    if ($this->hasAttribute(self::ATTRIBUTE_FIELD))
    {
      $sForm = $this->getAttribute(self::ATTRIBUTE_FORM);
      $sForm = $this->fixVar($sForm);

      $sField = $this->getAttribute(self::ATTRIBUTE_FIELD);

      $sName = $this->codeId($sForm) . '[' . $sField . ']';
      $sId = $sTag . \ucfirst($sField);
      $sValue = '{$oValues->get(\'' . $sForm . '\')->' . $sField . '->getRaw()}';

      $this->aContentAttributes = $aAttributes;
      $sOutput = '';

      switch ($sTag)
      {
        case 'div':
          $sClass = '{$oValues->get(\'' . $sForm . '\')' .
            '->getValidationStateClass(\'' . $sField . '\')}';
          if (isset($aAttributes['class']))
          {
            $sClass = $aAttributes['class'] . ' ' . $sClass;
          }
          $this->aContentAttributes['class'] = $sClass;
          break;
        case 'input':
        case 'textarea':
          $this->aContentAttributes['name'] = $sName;
          $this->aContentAttributes['id'] = $sId;
          if ($sTag != 'textarea')
          {
            $this->aContentAttributes['value'] = $sValue;
          }
          else
          {
          //  $this->sContentPostTag = self::endHeredoc() . $sValue . ' ' . self::startHeredoc();
            $this->sContentPostTag = $sValue;
          }

          //required
          $sOutput = self::endHeredoc() . 'if ($oValues->get(\'' . $sForm . '\')' .
            '->' . $sField . '->hasProcessor(\'notempty\') == \TRUE) { ' .
            self::startHeredoc();

          $sOutput .= ' required="required" ';
          $sOutput .= self::endHeredoc() . '} ' . self::startHeredoc();

          //maxlength
          $sOutput .= self::endHeredoc() . 'if ($oValues->get(\'' . $sForm . '\')' .
            '->' . $sField . '->hasProcessor(\'maxlength\') == \TRUE) { ' .
            '$aParams = $this->oValues->get(\'' . $sForm . '\')->' . $sField .
            '->getProcessorParams(\'maxlength\');' .
            self::startHeredoc();
          $sOutput .= ' data-parsley-maxlength="{$aParams[\'max\']}" ';
          $sOutput .= self::endHeredoc() . '} ' . self::startHeredoc();

          //minlength
          $sOutput .= self::endHeredoc() . 'if ($oValues->get(\'' . $sForm . '\')' .
            '->' . $sField . '->hasProcessor(\'minlength\') == \TRUE) { ' .
            '$aParams = $this->oValues->get(\'' . $sForm . '\')->' . $sField .
            '->getProcessorParams(\'minlength\');' .
            self::startHeredoc();

          $sOutput .= ' data-parsley-minlength="{$aParams[\'min\']}" ';
          $sOutput .= self::endHeredoc() . '} ' . self::startHeredoc();
          break;
        case 'label':
          $this->aContentAttributes['for'] = $sId;
          break;
        case 'select':
          $this->aContentAttributes['name'] = $sName;
          $this->aContentAttributes['id'] = $sId;
          //$this->aAttributesTriggered['input:value'] = $sValue;
          break;
        default:
          $this->sContentPostTag = '';
      }
      $this->sContentInTag = $sOutput;
    }
  }

  /** PROTECTED ***********************************************************************************/

  protected $aAllowedAttributes = array(
    self::ATTRIBUTE_FORM, self::ATTRIBUTE_FIELD, 'validation', 'js');

  /** PRIVATE *************************************************************************************/

  private function fixVar($sForm)
  {
    if ($sForm[0] === '$')
    {
      $sForm = \substr($sForm, 1);
    }
    return $sForm;
  }

  private function codeId($sForm)
  {
    $sId = '{$oValues->get(\'' . $sForm . '\')->getId()}';
    return $sId;
  }
}